package com.carey.blog.framework.latke.event;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Abstract event listener(Observer).
 * 
 * @param <T>
 *            the type of event data
 */
public abstract class AbstractEventListener<T> {

	/**
	 * Logger.
	 */
	private static final Logger LOGGER = Logger
			.getLogger(AbstractEventListener.class.getName());
	/**
	 * Event manager.
	 */
	private EventManager eventManager;

	/**
	 * Gets the event type of this listener could handle.
	 * 
	 * @return event type
	 */
	public abstract String getEventType();

	/**
	 * Constructs an {@link AbstractEventListener} object and register it with
	 * the specified event manager.
	 * 
	 * @param eventManager
	 *            the specified event manager
	 */
	public AbstractEventListener(final EventManager eventManager) {
		this.eventManager = eventManager;

		register();
	}

	/**
	 * Performs the listener {@code action} method with the specified event
	 * queue and event.
	 * 
	 * @param eventQueue
	 *            the specified event
	 * @param event
	 *            the specified event
	 * @throws EventException
	 *             event exception
	 * @see #action(com.carey.blog.framework.latke.event.Event)
	 */
	final void performAction(final AbstractEventQueue eventQueue,
			final Event event) throws EventException {
		final Event<T> eventObject = (Event<T>) event;
		try {
			action(eventObject);
		} finally {
			// remove event from event queue
			if (eventQueue instanceof SynchronizedEventQueue) {
				final SynchronizedEventQueue synchronizedEventQueue = (SynchronizedEventQueue) eventQueue;
				synchronizedEventQueue.removeEvent(eventObject);
			}
		}
	}

	/**
	 * Processes the specified event.
	 * 
	 * @param event
	 *            the specified event
	 * @throws EventException
	 *             event exception
	 */
	public abstract void action(final Event<T> event) throws EventException;

	/**
	 * Registers this listener to event manager.
	 */
	private void register() {
		eventManager.registerListener(this);
		LOGGER.log(
				Level.FINER,
				"Registered an event listener[classSimpleName={0}, eventType={1}]",
				new Object[] { getClass().getSimpleName(), getEventType() });
	}
}
